package ru.ifmo.thesis.solver.gp;

import org.jgap.Genotype;

import ru.ifmo.thesis.domain.Shedule;
import ru.ifmo.thesis.quantities.Minutes;
import ru.ifmo.thesis.quantities.Percent;
import ru.ifmo.thesis.util.Algorithms;

public class NotFarFromBest implements CompletionRule {

	private static final double NANOS_IN_MINUTE = (60 * Math.pow(10, 9));

	private final double bestAnswer;
	
	private final Percent acceptableDeviation;

	private Integer maxAttempts;
	
	private int currAttempts = 0;
	
	private long started = System.nanoTime();
	
	private Double maxTime;
	
	public NotFarFromBest(double bestAnswer, Percent acceptableDeviation, Integer maxAttempts) {
		this.bestAnswer = bestAnswer;
		this.acceptableDeviation = acceptableDeviation;
		this.maxAttempts = maxAttempts;
	}
	
	public NotFarFromBest(double bestAnswer, Percent acceptableDeviation, Minutes maxTime) {
		this.bestAnswer = bestAnswer;
		this.acceptableDeviation = acceptableDeviation;
		this.maxTime = maxTime.value();
	}

	@Override
	public boolean isTaskCompleted(Genotype population) {
		if (maxAttempts != null) {
			if (currAttempts++ > maxAttempts) {
				return true;
			}
		} else {
			double currentDelta = (System.nanoTime() - started) / NANOS_IN_MINUTE;
			if (currentDelta > maxTime) {
				return true;
			}
		}
		
		Shedule shedule = Algorithms.constructShedule(population.getFittestChromosome());
		double sheduleCost = Algorithms.calculateSheduleCost(shedule);
		if (sheduleCost < bestAnswer) {
			return true;
		} 
		double deviation = (sheduleCost - bestAnswer) / sheduleCost;
		return deviation < acceptableDeviation.value();
	}

	@Override
	public CompletionRule newCopy() {
		return new NotFarFromBest(bestAnswer, acceptableDeviation, maxAttempts);
	}
}